#include "bsp/cpu_driver.h"
#include "pc_message.h"
#include "os/os.h"

bool process_iap_message(message_t *can_message) {
	uint8_t response[24];
	uint8_t rsplen;
	encoder_key(response, can_message->key);
	response[2] = 0;
	rsplen = 3;
	switch(can_message->key) {
		case BUILD_CMD_KEY(0xF0):
			flash_write_magic(MAGIC_ENTER_BOOT);
			cpu_reboot();
			break;
		case BUILD_CMD_KEY(0xF5):
			memcpy(response + rsplen, can_message->data, can_message->len);
			rsplen += can_message->len;
			break;
		case BUILD_CMD_KEY(0xF9):
			flash_write_magic(MAGIC_APP_BOOT_OK);
			break;
		case BUILD_CMD_KEY(0xF6):
			if (can_message->len > 0 && can_message->data[0] == 0x01) {
				rsplen += mcu_chip_id(response + 4) + 1;
				response[3] = 0x00;
			}
			break;
		case BUILD_CMD_KEY(0xF8):
			iap_read_string(can_message->src, can_message->data, can_message->from);
			rsplen = 0;
			break;
		default:
			return false;
	}
	if (rsplen > 0) {
		iap_send_data(can_message->src, response, rsplen, can_message->from);
	}
	return true;
}

void iap_read_string(uint8_t can, const uint8_t *args, u8 from)
{
	#define buff_len 256
	uint8_t buff[buff_len];
	const char *text;
	uint32_t addr;
	uint32_t len;

	addr = ((uint32_t) args[2]) << 16 | ((uint32_t) args[1]) << 8 | args[0];
	u32 offset = addr;
#if defined(STM32F4)
	/* 兼容16K的bootloader + 16K info*/
	if (addr == 0x2A00) {
		offset = 0x8A00;
	}else if (addr == 0x2800) {
		offset = 0x8800;
	}else if (addr == 0x2C00) {
		offset = 0x8C00;
	}
#elif defined (STM32G4)
#if defined(CONFIG_BOARD_USB2CAN)
	/* 兼容16K的bootloader + 4K info*/
	if (addr == 0x2A00) {
		offset = 0x5A00;
	}else if (addr == 0x2800) {
		offset = 0x5800;
	}else if (addr == 0x2C00) {
		offset = 0x5C00;
	}
#else
	/* 兼容8K的bootloader + 4K info*/
	if (addr == 0x2A00) {
		offset = 0x3A00;
	}else if (addr == 0x2800) {
		offset = 0x3800;
	}else if (addr == 0x2C00) {
		offset = 0x3C00;
	}
#endif /* CONFIG_BOARD_USB2CAN */
#endif /* STM32F4 */


	text = (const char *) (CONFIG_FLASH_ADDRESS + offset);

	len = strlen(text);
	if (len > buff_len) {
		len = buff_len;
	}

	buff[0] = 0xF8;
	buff[1] = MY_MESSAGE_ADDR;
	buff[2] = 0x00;
	memcpy(buff + 3, args, 3);
	memcpy(buff + 6, text, len);

	iap_send_data(can, buff, len + 6, from);
}


void iap_send_data(uint8_t can, uint8_t *data, int len, u8 from){
	u32 head_id = response_head(can);
	if (from == MSG_DEV_CAN) {
		can_send_message(head_id, data, len);
	}else {
		serial_send_message(head_id, data, len);
	}
}

